#include "mymodel.h"

const struct aiScene* scene = NULL;

//void MyModel::Draw(QOpenGLShaderProgram *program)
//{
////    for(unsigned int i = 0; i < meshes.size(); i++)
////        meshes[i].Draw(program);
//}

void MyModel::loadModel(QString path)
{
    qInfo()<<__FUNCTION__<<path;
    scene = aiImportFile(path.toUtf8().data(), aiProcess_Triangulate | aiProcess_FlipUVs);
    if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
    {
        cout << "ERROR::ASSIMP::" << aiGetErrorString() << endl;
        return;
    }
//    directory = path.substr(0, path.find_last_of('/'));
    directory = path.left(path.lastIndexOf('/'));

    processNode(scene->mRootNode, scene);
}

void MyModel::processNode(aiNode *node, const aiScene *scene)
{
//    qInfo()<<__FUNCTION__;
    // 处理节点所有的网格（如果有的话）
    for(unsigned int i = 0; i < node->mNumMeshes; i++)
    {
        aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
        meshes.push_back(processMesh(mesh, scene));
    }
    // 接下来对它的子节点重复这一过程
    for(unsigned int i = 0; i < node->mNumChildren; i++)
    {
        processNode(node->mChildren[i], scene);
    }
}

MyMesh MyModel::processMesh(aiMesh *mesh, const aiScene *scene)
{
//    qInfo()<<__FUNCTION__;
    // data to fill
    vector<Vertex> vertices;
    vector<unsigned int> indices;
    vector<Texture> textures;

    // walk through each of the mesh's vertices
    for(unsigned int i = 0; i < mesh->mNumVertices; i++)
    {
        Vertex vertex;
        QVector3D vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder QVector3D first.
        // positions
        vector.setX(mesh->mVertices[i].x);
        vector.setY(mesh->mVertices[i].y);
        vector.setZ(mesh->mVertices[i].z);
        vertex.Position = vector;
        // normals
        if (mesh->HasNormals())
        {
            vector.setX(mesh->mNormals[i].x);
            vector.setY(mesh->mNormals[i].y);
            vector.setZ(mesh->mNormals[i].z);
            vertex.Normal = vector;
        }
        // texture coordinates
        if(mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
        {
            QVector2D vec;
            // a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
            // use models where a vertex can have multiple texture coordinates so we always take the first set (0).
            vec.setX(mesh->mTextureCoords[0][i].x);
            vec.setY(mesh->mTextureCoords[0][i].y);
            vertex.TexCoords = vec;
            // tangent
//            if(mesh->mTangents != 0)
//            {
//                vector.setX(mesh->mTangents[i].x);
//                vector.setY(mesh->mTangents[i].y);
//                vector.setZ(mesh->mTangents[i].z);
//                vertex.Tangent = vector;
//            }

//            // bitangent
//            if(mesh->mBitangents != 0)
//            {
//                vector.setX(mesh->mBitangents[i].x);
//                vector.setY(mesh->mBitangents[i].y);
//                vector.setZ(mesh->mBitangents[i].z);
//                vertex.Bitangent = vector;
//            }
        }
        else
            vertex.TexCoords = QVector2D(0.0f, 0.0f);

        vertices.push_back(vertex);
    }
    // now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
    for(unsigned int i = 0; i < mesh->mNumFaces; i++)
    {
        aiFace face = mesh->mFaces[i];
        // retrieve all indices of the face and store them in the indices vector
        for(unsigned int j = 0; j < face.mNumIndices; j++)
            indices.push_back(face.mIndices[j]);
    }
    // process materials
    aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];

    for(unsigned int i = 0; i < material->GetTextureCount(aiTextureType_DIFFUSE); i++)
    {
        aiString str;
        material->GetTexture(aiTextureType_DIFFUSE, i, &str);
        qInfo()<<"aiTextureType_DIFFUSE" << QString(str.data);
        if(QString(str.data).trimmed().isEmpty()) continue;
        Texture t;
        t.path = QString(str.data);
        t.type = "texture_diffuse";
        textures.push_back(t);
    }
    for(unsigned int i = 0; i < material->GetTextureCount(aiTextureType_DIFFUSE); i++)
    {
        aiString str;
        material->GetTexture(aiTextureType_SPECULAR, i, &str);
        qInfo()<<"aiTextureType_SPECULAR" << QString(str.data);
        if(QString(str.data).trimmed().isEmpty()) continue;
        Texture t;
        t.path = QString(str.data);
        t.type = "texture_specular";
        textures.push_back(t);
    }
    for(unsigned int i = 0; i < material->GetTextureCount(aiTextureType_DIFFUSE); i++)
    {
        aiString str;
        material->GetTexture(aiTextureType_HEIGHT, i, &str);
        qInfo()<<"aiTextureType_HEIGHT" << QString(str.data);
        if(QString(str.data).trimmed().isEmpty()) continue;
        Texture t;
        t.path = QString(str.data);
        t.type = "texture_normal";
        textures.push_back(t);
    }
    for(unsigned int i = 0; i < material->GetTextureCount(aiTextureType_DIFFUSE); i++)
    {
        aiString str;
        material->GetTexture(aiTextureType_AMBIENT, i, &str);
        qInfo()<<"aiTextureType_AMBIENT" << QString(str.data);
        if(QString(str.data).trimmed().isEmpty()) continue;
        Texture t;
        t.path = QString(str.data);
        t.type = "texture_height";
        textures.push_back(t);
    }

    // return a mesh object created from the extracted mesh data
    return MyMesh(vertices, indices, textures);
}
